﻿/*
    Bisounours Party Updater - Update Source Engine Mods
    Copyright (C) 2012  Louis «Orygin» Geuten and Hekar Khani

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   
    Bisounours Party Updater  
    Copyright (C) 2012  Louis «Orygin» Geuten and Hekar Khani
    This program comes with ABSOLUTELY NO WARRANTY;
    This is free software, and you are welcome to redistribute it
    under certain conditions;
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpSvn;
using System.IO;

namespace bpUpdater
{
    /// <summary>
    /// Updater made for SVN
    /// </summary>
    class SvnUpdater : Updater
    {
        public const string Method = "svn";
        private string _gameDir;
        private string _targetUrl;
        private int _localVersion;
        private int _serverVersion;
        private bool _installRequired;

        public SvnUpdater(string gameDir, string targetUrl)
        {
            _installRequired = !Directory.Exists(gameDir);
            this._gameDir = gameDir;
            this._targetUrl = targetUrl;
        }

        public void CleanUp()
        {
            var targetUrl = new SvnUriTarget(_targetUrl);
            var client = new SvnClient();
            try
            {
                client.CleanUp(_gameDir);
            }
            catch (SvnInvalidNodeKindException)
            {
                // ignore for now...
            }
        }

        public void RetrieveAndUpdate(bool NeedToClean, string updateUrl, 
            string WorkDir, Logger logger)
        {
            WorkDir = Path.GetDirectoryName(WorkDir);
            SvnTarget target;
            SvnTarget.TryParse(updateUrl, out target);

            var targetUrl = new SvnUriTarget(updateUrl);
            var client = new SvnClient();
            try
            {
                SvnInfoEventArgs info;
                SvnTarget localTarget;
                SvnTarget.TryParse(WorkDir, out localTarget);
                client.GetInfo(localTarget, out info);
            }
            catch (SvnInvalidNodeKindException)
            {
                _installRequired = true;
            }

            if (_installRequired)
            {
                Directory.CreateDirectory(WorkDir);

                // Do a checkout
                logger.LogLine(String.Format("Installing from {0} to {1}...", targetUrl, WorkDir));
                if (!client.CheckOut(targetUrl, WorkDir))
                {
                    logger.LogLine(String.Format("Failure to install from {0} to {1}", targetUrl, WorkDir));
                }
                else
                {
                    logger.LogLine(String.Format("Successfully checked out."));
                    _localVersion = _serverVersion;
                    _installRequired = false;
                }
            }
            else
            {
                // Do an update
                logger.LogLine(String.Format("Updating from {0} to {1}...", targetUrl, WorkDir));
                if (!client.Update(WorkDir))
                {
                    logger.LogLine(String.Format("Failure to check from {0} to {1}", targetUrl, WorkDir));
                }
                else
                {
                    logger.LogLine(String.Format("Successfully updated."));
                    _localVersion = _serverVersion;
                }
            }
        }

        public bool InstallRequired
        {
            get
            {
                return _installRequired;
            }
        }

        public bool UpdateRequired
        {
            get { return Iterations > 0; }
        }

        public int Iterations
        {
            get { return _serverVersion - _localVersion; }
        }

        public int LocalVersion
        {
            get
            {
                if (InstallRequired)
                {
                    _localVersion = 0;
                    return _localVersion;
                }

                SvnTarget target;
                SvnTarget.TryParse(_gameDir, out target);

                var targetUrl = new SvnUriTarget(_gameDir);
                var client = new SvnClient();
                SvnInfoEventArgs info;
                client.GetInfo(target, out info);

                _localVersion = Convert.ToInt32(info.Revision);
                return _localVersion;
            }
        }

        public int ServerVersion
        {
            get
            {
                if (InstallRequired)
                {
                    _serverVersion = 1;
                    return _serverVersion;
                }

                SvnTarget target;
                SvnTarget.TryParse(_targetUrl, out target);

                var targetUrl = new SvnUriTarget(_targetUrl);
                var client = new SvnClient();
                SvnInfoEventArgs info;
                client.GetInfo(target, out info);

                _serverVersion = Convert.ToInt32(info.Revision);
                return _serverVersion;
            }
        }

        public void DeleteFiles()
        {
            try
            {
                Directory.Delete(Path.GetDirectoryName(_gameDir) + Path.DirectorySeparatorChar + ".svn");
                Directory.Delete(_gameDir);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
            }
        }
    }
}
